package com.algo.sentiment;

/**
 * Created by supertool on 2014/10/29.
 */

import org.javatuples.Pair;
import org.javatuples.Sextet;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;

public class SentimentMatch {
    private ChineseWordsSegment cws;
    private Map<String,Item> words;

    public SentimentMatch(Map<String, Item> words) {
        this.words = words;
    }

    public SentimentMatch(ChineseWordsSegment cws, Map<String, Item> words) {
        this.cws = cws;
        this.words = words;
    }

    public SentimentMatch(String propertyFile) {
        Dictionary dictionary = new Dictionary(propertyFile);
        Sentiment sentiment = new Sentiment(dictionary.getDictFilesMap());
        Map<String, Item> m = sentiment.getWordItemMap();
        ChineseWordsSegment cws = new ChineseWordsSegment();
        cws.initDict(dictionary.getUserDict());
        this.cws = cws;
        this.words = m;
    }
    /*
     *about groupId
     *-1 negative, 1 positive, 0 notword, 2 degree words ,3 punct, 4 noise words, 5 keywords, 6 question word
     */

    //  type 1 for base analysis, 2 for to analysis, 3 for nlp analysis, 4 for index analysis
    public Sextet<Double, Double, Double, Double, Double, Double> scoreCWS(String line, Integer type) {
//        List<Pair<String, String>> wordListWithNature = cws.segmentWordsWithFilledNatureNlp(line);
        List<Pair<String, String>> wordListWithNature = null;
        switch (type) {
            case 1:
                wordListWithNature = cws.segmentWordsWithFilledNatureBase(line);
                break;
            case 2:
                wordListWithNature = cws.segmentWordsWithFilledNatureTo(line);
                break;
            case 3:
                wordListWithNature = cws.segmentWordsWithFilledNatureNlp(line);
                break;
            case 4:
                wordListWithNature = cws.segmentWordsWithFilledNatureIndex(line);
                break;
            default:
                return null;
        }
        Integer len = wordListWithNature.size();
//        var (ePos, eNeg, eNot, eDeg, ePun, eSen) = Tuple6(-1,-1,-1,-1,-1, -1)
        Integer ePos = -1;
        Integer eNeg = -1;
        Integer eNot = -1;
        Integer eDeg = -1;
        Integer ePun = -1;
        Integer eSen = -1;

        Double sumScore = 0.0;
        Double wDeg = 1.0;
        Double nPos = 0.0;
        Double nNeg = 0.0;
        Double nQue = 0.0;//疑问词的位置
        Double sumPos = 0.0;
        Double sumNeg = 0.0;
        Double senScore = 0.0; // the score of the pre sentiment words, used to consider the influence of the not word after sentiment word

        for (int j = 0; j < len; j++) {
            Pair<String, String> wordPair = wordListWithNature.get(j);
            String wd = wordPair.getValue0();
            String word = "";
            Integer i = -1;
            if (words.containsKey(wd) || j == 0) {
                word = wd;
                i = j;
            } else {
                word = wordListWithNature.get(j - 1).getValue0() + wd;
                i = j - 1;
            }
            if (!words.containsKey(word)) {
                continue;
            }
            Double tmp = words.get(word).getWeight();
            switch (words.get(word).getGroupId()) {
                case -1: {
                    eNeg = i;
                    eSen = i;
                    nNeg += 1;
                    if (eNot != -1 && ePun < eNot && eNeg != eNot && eNeg - eNot <= 3) {
                        tmp *= -1;
                        nNeg -= 1;
                        nPos += 1;
                    }
                    if (eDeg != -1 && ePun < eDeg && eNeg != eDeg && eNeg - eDeg <= 3) {
                        tmp *= wDeg;
                    }
                    senScore = tmp;
                    break;
                }
                case 0: {
                    eNot = i;
                    tmp *= 0;
                    /*if (eSen != -1 && ePun < eSen && eNot - eSen <= 2) {
                        tmp = senScore * -1;
                    }*/
                    break;
                }
                case 1: {
                    ePos = i;
                    eSen = i;
                    nPos += 1;
                    if (eNot != -1 && ePun < eNot && ePos != eNot && ePos - eNot <= 3) {
                        tmp *= -1;
                        nPos -= 1;
                        nNeg += 1;
                    }
                    if (eDeg != -1 && ePun < eDeg && ePos != eDeg && ePos - eDeg <= 3) {
                        tmp *= wDeg;
                    }
                    senScore = tmp;
                    break;
                }
                case 2: {
                    eDeg = i;
                    wDeg = tmp;
                    tmp *= 0;
                    break;
                }
                case 3: {
                    ePun = i;
                    tmp *= 0;
                    if (word.equals("?") || word.equals("？")) {
                        nQue += 1.0;
                    }
                    break;
                }
                case 6: {
                    nQue += 1.0;
                    break;
                }
            }
            sumScore += tmp;
            if (tmp > 0) sumPos += tmp;
            else if (tmp < 0) sumNeg += tmp;
        }
        return new Sextet<Double, Double, Double, Double, Double, Double>(sumScore, sumPos, nPos, sumNeg, nNeg, nQue);
    }


    public Sextet<Double, Double, Double, Double, Double, Double> scoreCWSBase(String line) {
        return scoreCWS(line, 1);
    }

    public Sextet<Double, Double, Double, Double, Double, Double> scoreCWSTo(String line) {
        return scoreCWS(line, 2);
    }


    public Sextet<Double, Double, Double, Double, Double, Double> scoreCWSNlp(String line) {
        return scoreCWS(line, 3);
    }

    public Sextet<Double, Double, Double, Double, Double, Double> scoreCWSIndex(String line) {
        return scoreCWS(line, 4);
    }

    // 1 for positive, 2 for neu, 3 for negative, 4 for question
    public Integer sentimentDegree(String line) {

        Sextet<Double, Double, Double, Double, Double, Double> scores = scoreCWSTo(line);
        Integer degree = 0;
        Double sumScore = scores.getValue0();//
        Double nQue = scores.getValue5();//question
        if(sumScore > 0 && nQue ==0.0 ){
            degree = 1;
        }
        else if (sumScore == 0 && nQue == 0.0) {
            degree = 2;
        }
        else if (sumScore < 0 && ((sumScore > -1 && nQue == 0) || (sumScore < -1))) {
            degree = 3;
        }
        else {
            degree = 4;
        }
        return degree;
    }

    public void init(String fileName) {

    }

    public static void main(String[] args) {

//        Map<String,Item> m = new HashMap<String,Item>() {{
//            put("好",new Item(1,2.0));
//            put("不好",new Item(-1,-2.0));
//            put("不",new Item(0,1.5));
//            put(",",new Item(3,0.0));
//            put("?",new Item(3,0.0));
//        }}
        String propertyFile = "dict.properties";
//        Dictionary dictionary = new Dictionary(propertyFile);
//        Sentiment sentiment = new Sentiment(dictionary.getDictFilesMap());
//        Map<String, Item> m = sentiment.getWordItemMap();
//        ChineseWordsSegment cws = new ChineseWordsSegment();
//        cws.initDict(dictionary.getUserDict());
//        SentimentMatch sm = new SentimentMatch(cws, m);
        SentimentMatch sm = new SentimentMatch(propertyFile);
        System.out.println("Begin to insert a line:");
        try {
            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

            String aline;
            //从缓冲流读取一行数据
            aline = in.readLine();
            while (aline != null) {

                System.out.println(aline);
//                System.out.println(sm.scoreCWSBase(aline));
                System.out.println(sm.scoreCWSTo(aline));
                aline = in.readLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


}
